package com.otom.bcel;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.otom.bcel.annotations.MapClassList;
import com.otom.bcel.annotations.MapClassTo;

public class ClassMapping extends BaseObject {
	private Set<ClassInfo> classInfoList = new HashSet<ClassInfo>();
	
	public Set<ClassInfo> getClassInfoList() {
		return classInfoList;
	}

	public void setClassInfoList(Set<ClassInfo> classInfoList) {
		this.classInfoList = classInfoList;
	}

	public void initFromAnnotations(Class<?>[] clazzList) {
		for (Class<?> source : clazzList) {
			MapClassTo mapClassTo = source.getAnnotation(MapClassTo.class);			
			MapClassList mapClassList = source.getAnnotation(MapClassList.class);
			
			if (mapClassTo != null) {
				initFromAnnotation(source, mapClassTo);
			}
			
			if (mapClassList != null) {
				for (MapClassTo mapClassTo2 : mapClassList.value()) {
					initFromAnnotation(source, mapClassTo2);
				}
			}
		}
	}

	private void initFromAnnotation(Class<?> source, MapClassTo mapClassTo) {
		ClassInfo classInfo = new ClassInfo();						
		classInfo.initFromAnnotations(source, mapClassTo);
		classInfoList.add(classInfo);
		
		if (classInfo.isBiDirectional()) {
			classInfoList.add(classInfo.getBiDirectionalClassInfo());
		}
		
		if (!classInfo.getDependentClasses().isEmpty()) {
			generateDependentClasses(classInfo);					
		}
	}

	private void generateDependentClasses(ClassInfo classInfo) {
		List<ClassMapper> dependentClasses = classInfo.getDependentClasses();
		Iterator<ClassMapper> dependentClassesIterator = dependentClasses.iterator();
		
		while (dependentClassesIterator.hasNext()) {						
			ClassMapper classMapper = dependentClassesIterator.next();
			ClassInfo dependentClassInfo = new ClassInfo();
			dependentClassInfo.setBiDirectional(classInfo.isBiDirectional());
			dependentClassInfo.setMapWildCard(classInfo.isMapWildCard());
			dependentClassInfo.setSource(classMapper.getSource());
			dependentClassInfo.setDestination(classMapper.getDestination());
			
			classInfoList.add(dependentClassInfo);
			
			dependentClassInfo.initFieldsFromAnnotations(dependentClassInfo.getSource());
			
			if (classInfo.isBiDirectional()) {
				classInfoList.add(dependentClassInfo.getBiDirectionalClassInfo());
			}
			
		}
	}

}
